#include "httpmanager.h"
#include "httprequest.h"
#include "httpresponse.h"
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <sstream>

#include <boost/utilities.hpp>
#include <boost/asio.hpp>
#include <boost/regex.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/regex.hpp>
#include <boost/tokenizer.hpp>


using namespace std;
using boost::format;
using boost::lexical_cast;

HTTPManager::HEADER_T HTTPManager::DEFAULT_HEADER;
HTTPManager::REQUEST_DATA_T HTTPManager::DEFAULT_REQUEST_DATA;
bool HTTPManager::is_static_member_initialized = false;
boost::asio::io_service HTTPManager::ios;

int split_url(const string& url, string& protocal, string& site, unsigned& port, string& path)
{
	size_t pos = url.find( "://" );
	BOOST_ASSERT_MSG( pos != string::npos, (format("Invalid url : %s") % url).str().c_str() );
	protocal = url.substr(0, pos);
	site = url.substr(pos + 3 );
	
	size_t port_pos = site.find_first_of(':');
	size_t path_pos = site.find_first_of('/');

	if ( string::npos != port_pos && string::npos != path_pos ){
		port = lexical_cast<unsigned int>(site.substr( port_pos, path_pos ));
		path = site.substr( path_pos );
		site = site.substr(0, port_pos );
	}else if ( string::npos != path_pos ){
			path = site.substr( path_pos );
			site = site.substr(0, path_pos);
	}else{
		// do nothing
	}
	return 0;
}

HTTPResponse HTTPManager::urlopen(const string& url, const REQUEST_DATA_T& data, const HEADER_T& header, unsigned int timeout)
{
	if( !HTTPManager::is_static_member_initialized )
	{
		HTTPManager::init_static_member();
		HTTPManager::is_static_member_initialized = true;
	}

	string protocal, site, path("/");
	unsigned int port = 80;
	split_url( url, protocal, site, port, path);
	//cout << format("protocal : %s, site : %s, port: %u, path : %s") % protocal % site % port % path << endl;
	
	boost::asio::ip::tcp::iostream stream;
	stream.expires_from_now(boost::posix_time::seconds(timeout));
	stream.connect( (format("%s") % site).str(), protocal);
	if( !stream )
	{
		cout << "cannot connect!" << endl;
		cout << stream.error() << endl;
		return HTTPResponse();
	}else{
		//cout << "connect succeed!" << endl;
	}
	
	HEADER_CONST_ITER_T iter = header.begin();
	format line("%s: %s\r\n");
	stream << ( format("GET %s HTTP/1.0\r\n") % path).str();
	stream << (line % "Host" % site).str();
	while( header.end() != iter )
	{
		stream << (line % iter->first % iter->second ).str();
		++iter;
	}

	stream << "\r\n";
	stream.flush();
	ostringstream ss;
	ss << stream.rdbuf();
	return HTTPManager::MakeHTTPResponse( ss.str() );
}

HTTPResponse HTTPManager::MakeHTTPResponse(const string& content)
{
	using namespace boost;
	HTTPResponse response;
	vector< string > results;
	split_regex( results, content, regex("\r\n\r\n") );
	
	string header_content( results[0] );
	string body_content( results[1] );
	trim( body_content );

	split_regex( results, header_content, regex("\r\n") );
	BOOST_ASSERT_MSG( results.size() != 0, "Invalid header !");
	
	string status_line( results[0] );
	vector< string > header_split_results;
	for(size_t pos = 1; pos != results.size(); ++pos )
	{
		string& line( results[pos] );
		size_t first_colon_pos = line.find_first_of(":");
		BOOST_ASSERT_MSG( first_colon_pos != string::npos, (format("Invalid header line : %s") % line).str().c_str() );
		string key( line.substr(0, first_colon_pos ) );
		string value( line.substr(first_colon_pos + 1) );
		trim(key);
		trim(value);
		response.header_[ key ] = value;
	}
	response.header_[ "body" ] = body_content;
	return response;
}

void HTTPManager::init_static_member()
{
	HTTPManager::DEFAULT_HEADER["User-Agent"] = "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/536.26.14 (KHTML, like Gecko) Version/6.0.1 Safari/536.26.14\r\n";
	HTTPManager::DEFAULT_HEADER["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
	HTTPManager::DEFAULT_HEADER["Connection"] = "close";
	HTTPManager::DEFAULT_HEADER["Accept-Charset"] = "utf-8;q=0.7,*;q=0.3";
	HTTPManager::DEFAULT_HEADER["Accept-Language"] = "zh-CN,zh;q=0.8";
}

HTTPManager::HTTPManager()
{
}

HTTPManager::~HTTPManager()
{
}

//HTTPResponse HTTPManager::urlopen(const string& url, const REQUEST_DATA_T& data, const HEADER_T& header, unsigned int timeout)
HTTPResponse HTTPManager::urlopen(const HTTPRequest& req)
{
	REQUEST_DATA_T data;
	req.get_request_data( data );
	BOOST_FOREACH(const Opener& opener, this->openers)
	{
		opener.
	}

}
